package absc.object;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import absc.util.Constantes;

@SuppressWarnings("deprecation")
public class SWOTObject {
	
	private String swotPathFile;
	private DocumentBuilder build;
	private DocumentBuilderFactory factory;
	private Document docSWOT;
	private DOMImplementation dom;
	private Element noRoot, noStrenght, noWeaknesses, noOpportunities, noThreats;
	private XPath xpath;
	
	public SWOTObject(){
		try{
		    factory = DocumentBuilderFactory.newInstance();
	        factory.setNamespaceAware(true);	         
	        build = factory.newDocumentBuilder();
	        dom = this.build.getDOMImplementation();
	        xpath = XPathFactory.newInstance().newXPath();
		}
		catch(Exception e){
			e.printStackTrace();			
		}
	}
	
	public void createSWOT(String swotName, String pathFile){
		this.swotPathFile = pathFile + "\\" + swotName + ".swo";
		
		makeFile();
	}
	
	public void loadSWOT(String path){
		this.swotPathFile = path;
		
		try{
			this.docSWOT = this.build.parse(path);
			this.noRoot = this.docSWOT.getDocumentElement();
			this.noStrenght = (Element) this.noRoot.getElementsByTagName("Strenghts").item(0);
			this.noWeaknesses = (Element) this.noRoot.getElementsByTagName("Weaknesses").item(0);
			this.noOpportunities = (Element) this.noRoot.getElementsByTagName("Opportunities").item(0);
			this.noThreats = (Element) this.noRoot.getElementsByTagName("Threats").item(0);
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}

	private void makeFile() {
		try{			
			this.docSWOT = this.dom.createDocument(null, null, null);
			
			noRoot = this.docSWOT.createElement("SWOT");						
			
			noStrenght = this.docSWOT.createElement("Strenghts");
			noWeaknesses = this.docSWOT.createElement("Weaknesses");			
			noOpportunities = this.docSWOT.createElement("Opportunities");
			noThreats = this.docSWOT.createElement("Threats");
			
			noRoot.appendChild(noStrenght);
			noRoot.appendChild(noWeaknesses);
			noRoot.appendChild(noOpportunities);
			noRoot.appendChild(noThreats);
			
			this.docSWOT.insertBefore(noRoot, null);
			
			makeXML();
		}
		catch(Exception e){
			e.printStackTrace();
		}		
	}

	@SuppressWarnings("deprecation")
	private void makeXML() {
        FileWriter writer;
        BufferedWriter buf;
        OutputFormat format;
        XMLSerializer output;
        File tmp;
        
        try{
    		tmp = new File(this.swotPathFile);
            writer = new FileWriter(tmp);
            buf = new BufferedWriter(writer);            
            format = new OutputFormat(this.docSWOT, "ISO-8859-1", true);
            format.setLineSeparator(System.getProperty("line.separator"));
            output = new XMLSerializer(buf, format);
            output.serialize(this.docSWOT);
        } catch(Exception e){
            e.printStackTrace();
        }			
	}

	public void addItem(String nomeItem, int itemTipo) {
		Element no;
		
		no = this.docSWOT.createElement("Item");
		no.setTextContent(nomeItem);
		
		if (itemTipo == Constantes.STRENGHT)
			this.noStrenght.appendChild(no);
		else if (itemTipo == Constantes.WEAKNESSES)
			this.noWeaknesses.appendChild(no);
		else if (itemTipo == Constantes.OPPORTUNITIES)
			this.noOpportunities.appendChild(no);
		else if (itemTipo == Constantes.THREATS)
			this.noThreats.appendChild(no);
		
		makeXML();
	}

	public List<String> getStrenghts() {
		return getItens(Constantes.STRENGHT);
	}

	private List<String> getItens(int tipo) {
		NodeList nl;
		String nome;
		List<String> lista;
		
		nome = "";
		
		if (tipo == Constantes.STRENGHT)
			nome = "Strenghts";
		else if (tipo == Constantes.WEAKNESSES)
			nome = "Weaknesses";
		else if (tipo == Constantes.OPPORTUNITIES)
			nome = "Opportunities";
		else if (tipo == Constantes.THREATS)
			nome = "Threats";
		
		try{
			lista = new ArrayList<String>();			
			nl = (NodeList) xpath.evaluate("//" + nome + "/Item", this.docSWOT, XPathConstants.NODESET);
			
			for(int i = 0; i < nl.getLength(); i++){
				Node no = nl.item(i);
				lista.add(no.getTextContent());
			}
		}
		catch(Exception e){
			e.printStackTrace();
			lista = null;
		}

		return lista;
	}

	public List<String> getWeaknesses() {
		return getItens(Constantes.WEAKNESSES);
	}

	public List<String> getOpportunities() {
		return getItens(Constantes.OPPORTUNITIES);
	}

	public List<String> getThreats() {
		return getItens(Constantes.THREATS);
	}

	public void updateItem(String nomeItem, int tipoItem, String nomeItemAntigo) {
		Node no;
		String nome;
		
		if (tipoItem == Constantes.STRENGHT)
			nome = "Strenghts";
		else if (tipoItem == Constantes.WEAKNESSES)
			nome = "Weaknesses";
		else if (tipoItem == Constantes.OPPORTUNITIES)
			nome = "Opportunities";
		else if (tipoItem == Constantes.THREATS)
			nome = "Threats";
		else
			nome = "";
		
		try{						
			no = (Node) xpath.evaluate("//" + nome + "/Item[text()='" + nomeItemAntigo + "']", this.docSWOT, XPathConstants.NODE);
			no.setTextContent(nomeItem);
			makeXML();
		}
		catch(Exception e){
			e.printStackTrace();
		}		
	}

	public void refresh() {
		try{
			this.docSWOT = this.build.parse(this.swotPathFile);
			this.noRoot = this.docSWOT.getDocumentElement();
			this.noStrenght = (Element) this.noRoot.getElementsByTagName("Strenghts").item(0);
			this.noWeaknesses = (Element) this.noRoot.getElementsByTagName("Weaknesses").item(0);
			this.noOpportunities = (Element) this.noRoot.getElementsByTagName("Opportunities").item(0);
			this.noThreats = (Element) this.noRoot.getElementsByTagName("Threats").item(0);
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}

	public void delItens(List<String> lista, int tipoItem) {
		for(String item: lista){
			deletaItem(item, tipoItem);
		}
		
		makeXML();
	}

	private void deletaItem(String item, int tipoItem) {
		Node no, noGrupo;
		String nome;
		
		if (tipoItem == Constantes.STRENGHT){
			nome = "Strenghts";
			noGrupo = this.noStrenght;
		}
		else if (tipoItem == Constantes.WEAKNESSES){
			nome = "Weaknesses";
			noGrupo = this.noWeaknesses;
		}
		else if (tipoItem == Constantes.OPPORTUNITIES){
			nome = "Opportunities";
			noGrupo = this.noOpportunities;
		}
		else if (tipoItem == Constantes.THREATS){
			nome = "Threats";
			noGrupo = this.noThreats;
		}
		else{
			nome = "";
			noGrupo = null;
		}
		
		try{						
			no = (Node) xpath.evaluate("//" + nome + "/Item[text()='" + item + "']", this.docSWOT, XPathConstants.NODE);
			noGrupo.removeChild(no);	
		}
		catch(Exception e){
			e.printStackTrace();
		}		
	}
}
